package noticeservice

import (
	"encoding/json"
	"fmt"
	"games.com/server/internal/pkg/config"
	pkghttp "games.com/server/internal/pkg/http"
	"net/http"
)

type noticeService struct {
	dao    *noticeDAO
	config *config.Config
}

func NewNoticeService(config *config.Config) (*noticeService, error) {
	as := &noticeService{config: config}

	dao, err := NewNoticeDAO(config)
	if err != nil {
		return nil, fmt.Errorf("failed to new Noticedao, err:%w", err)
	}
	as.dao = dao

	http.HandleFunc("/AddNotice", as.addNoticeHandler)
	http.HandleFunc("/DeleteNotice", as.deleteNoticeHandler)
	http.HandleFunc("/UpdateNotice", as.updateNoticeHandler)
	http.HandleFunc("/QueryNoticeCnt", as.queryNoticeCntHandler)
	http.HandleFunc("/QueryNotice", as.queryNoticeHandler)

	return as, nil
}

func (as *noticeService) addNoticeHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	var req Notice
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusBadRequest)
		return
	}

	ctx := r.Context()
	err = as.dao.InsertNotice(ctx, &req)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to insert notice, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}

	resJson, err := json.Marshal(&req)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(resJson)
}

type DeleteNoticeReq struct {
	ID int32 `json:"id"`
}

func (as *noticeService) deleteNoticeHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	var req DeleteNoticeReq
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusBadRequest)
		return
	}

	ctx := r.Context()
	err = as.dao.DeleteNotice(ctx, req.ID)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to delete notice, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
}

func (as *noticeService) updateNoticeHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	var req Notice
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusBadRequest)
		return
	}

	ctx := r.Context()

	record, err := as.dao.QueryNoticeByID(ctx, req.ID)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to query notice by id, err:%w", err).Error(), http.StatusBadRequest)
		return
	}

	record.Gm = req.Gm
	record.SendTime = req.SendTime
	record.ExitTime = req.ExitTime
	record.Content = req.Content

	err = as.dao.UpdateNotice(ctx, record)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to insert notice, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}

	resJson, err := json.Marshal(&record)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(resJson)
}

type QueryNoticeCntRes struct {
	Cnt int32 `json:"cnt"`
}

func (as *noticeService) queryNoticeCntHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	ctx := r.Context()
	cnt, err := as.dao.QueryNoticeCnt(ctx)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("query notice cnt failed, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}
	res := &QueryNoticeCntRes{Cnt: cnt}
	resJson, err := json.Marshal(res)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("query notice cnt failed, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(resJson)
}

type QueryNoticeReq struct {
	PageCapacity int32 `json:"page_capacity"`
	Page         int32 `json:"page"`
}
type QueryNoticeRes struct {
	Notice []*Notice `json:"notices"`
}

func (as *noticeService) queryNoticeHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodOptions {
		pkghttp.AllowCrossRegion(w)
		w.WriteHeader(http.StatusOK)
		return
	}

	if r.Method != http.MethodPost {
		pkghttp.HttpError(w, "only post method is allowed", http.StatusMethodNotAllowed)
		return
	}

	var req QueryNoticeReq
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusBadRequest)
		return
	}

	ctx := r.Context()
	notices, err := as.dao.QueryNotice(ctx, (req.Page-1)*req.PageCapacity, req.PageCapacity)
	if err != nil {
		pkghttp.HttpError(w, fmt.Errorf("failed to query notice, err:%w", err).Error(), http.StatusInternalServerError)
		return
	}
	res := QueryNoticeRes{Notice: notices}
	resJson, err := json.Marshal(&res)
	if err != nil {
		pkghttp.HttpError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	pkghttp.AllowCrossRegion(w)
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(resJson)
}
